package controler;

import java.lang.Math.*;
import java.util.*;

import model.SimulationSettings;

public class MonteCarloSimulation {

	public String order;
	public double S;
	public double X;
	public double T;
	public double r;
	public double b;
	public double v;
	public int nSteps;
	private int nSimulations;
	public double result;
	
	MonteCarloSimulation()
	{
		InitializeExampleValues();
	}

	public void run()
	{
		result = MonteCarloStandardOption ();
	}
	
	public void runWithAverage()
	{
		result = MonteCarloStandardOption ();
	}
	
	private void InitializeExampleValues()
	{
		S = 40;
		X = 50;
		T = 0.5;
		r = 0.06;
		b = 0.10;
		v = 0.45; 
		nSteps = 168; 
		nSimulations = 100000;
	}


	private double MonteCarloStandardOption ()
	{

		double dt; 
		double St;
		Random randomNo = new Random();

		double Sum = 0; double Drift; double vSqrdt;
		int i; int j; int z = 1; 

		dt = T/nSteps; 
		Drift = (b - v*v/2)*dt ;
		vSqrdt = v * java.lang.Math.sqrt(dt) ;
		if (order=="Call"){ 
			z = 1 ;
		}
		else if (order=="Put"){ 
			z = -1 ;
		}
		for (i = 1; i<=nSimulations; i++)
		{
			St = S ;
			for (j = 1; j<=nSteps; j++)
			{
				double randNumber = (double) randomNo.nextGaussian();
				St = St * java.lang.Math.exp(Drift + vSqrdt * randNumber); 
			}
			Sum = Sum +  java.lang.Math.max(z*(St - X), 0) ;
		}
		return (java.lang.Math.exp(-r*T)*(Sum/nSimulations)) ;

	}

	public void setOptions(SimulationSettings settings) {
		
		order = settings.orderType;
		S = settings.currentPrice;
		X = settings.strikePrice;
		T = settings.timeMaturity;
		r = settings.interest;
		b = settings.fees;
		v = settings.volatility;
		nSteps = (int) settings.steps;
		nSimulations = (int) settings.simulation;
		
		
	}


}